package com.fduss.mazegame.client.aui;

import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.graphics.RectF;
import android.os.Build;
import android.os.Bundle;
import android.support.annotation.RequiresApi;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.MotionEvent;
import android.view.View;
import android.view.Window;
import android.view.WindowManager;
import android.widget.Toast;

import com.fduss.mazegame.CLOptions;
import com.fduss.mazegame.R;
import com.fduss.mazegame.client.Localizer;
import com.fduss.mazegame.client.MsgToUsr;
import com.fduss.mazegame.core.unit.Hero;
import com.fduss.mazegame.core.unit.feature.Icon;
import com.fduss.mazegame.server.ClientView;
import com.fduss.mazegame.server.Server;
import com.fduss.mazegame.util.Direction;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.Map;

public class GameViewActivity extends Activity {

    protected Server server;
    protected Localizer localizer;
    private int cellWidth;
    private int cellHeight;
    private Map<Icon, Bitmap> imageMap = new HashMap<>();
    private GestureDetector detector;
    private boolean finished = false;

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        initGameSettings();
        initResources();

        // init view and let it update itself automatically
        setContentView(new GameView(this));

        // add controllers
        detector = new GestureDetector(this, new MyGestureListener());
    }

    private void initResources() {
        // add to image map
        imageMap.put(Icon.EMPTY, getBitmap(R.drawable.space));
        imageMap.put(Icon.WALL, getBitmap(R.drawable.wall));
        imageMap.put(Icon.HERO, getBitmap(R.drawable.hero));
        imageMap.put(Icon.FOOTPRINT, getBitmap(R.drawable.footprint));
        imageMap.put(Icon.MONSTER, getBitmap(R.drawable.monster));
        imageMap.put(Icon.END, getBitmap(R.drawable.end));
        imageMap.put(Icon.TREASURE, getBitmap(R.drawable.treasure));
    }

    private Bitmap getBitmap(int drawableId) {
        //获取图片资源
        InputStream is = this.getResources().openRawResource(drawableId);
        Bitmap bitmapTmp;
        try {
            bitmapTmp = BitmapFactory.decodeStream(is);
        } finally {
            try {
                is.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return bitmapTmp;
    }

    private Bitmap iconToImage(Icon icon) {
        return imageMap.get(icon);
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void initGameSettings() {
        //set full screen
        this.requestWindowFeature(Window.FEATURE_NO_TITLE);//remove tittle
        getWindow().setFlags(
                WindowManager.LayoutParams.FLAG_FULLSCREEN,
                WindowManager.LayoutParams.FLAG_FULLSCREEN
        );
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
//        // change screen orientation to landscape
//        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);

        //get height and width of current screen
        DisplayMetrics dm = new DisplayMetrics();
        getWindowManager().getDefaultDisplay().getMetrics(dm);
        int screenHeight = dm.heightPixels;
        int screenWidth = dm.widthPixels;

        Intent intent = getIntent();
        String[] args = {"-r", "31", "-c", "25"};
        String rowNum = intent.getStringExtra("rowNum");
        String colNum = intent.getStringExtra("colNum");
        if (!("".equals(rowNum) || "".equals(colNum))) {
            args[1] = rowNum;
            args[3] = colNum;
        }
        CLOptions options = new CLOptions(args);
        server = new Server(options.getServerSpec()).init();
        localizer = new Localizer(options.getLanguage());

        Icon[][] view = server.getClientView().getGameView();
        cellWidth = screenWidth / (view[0].length + 2);
        cellHeight = screenHeight / (view.length + 2);
//        Log.i("Cell", cellWidth + ", " + cellHeight);
    }

    @Override
    public boolean onTouchEvent(MotionEvent event) {
        detector.onTouchEvent(event);
        return true;
    }

    @RequiresApi(api = Build.VERSION_CODES.KITKAT)
    private void showScore(Hero hero) {
        Toast.makeText(this, String.format(
                localizer.get(MsgToUsr.SCORE),
                hero.getSteps(),
                hero.getKilling(),
                hero.getPicking()
        ), Toast.LENGTH_SHORT).show();
    }

    private RectF buildRectF(float left, float top) {
        return new RectF(left * cellWidth, top * cellHeight, (left + 1) * cellWidth, (top + 1) * cellHeight);
    }

    private void checkIsDied() {
        if (!server.isHeroAlive()) {
            Toast.makeText(this, "sorry, you died.", Toast.LENGTH_SHORT).show();
            finished = true;
            finish();
        }
    }

    private void checkIsWin() {
        if (server.isGameOver()) {
            Toast.makeText(this, "congratulations, you win.", Toast.LENGTH_SHORT).show();
            finished = true;
            finish();
        }
    }

    public class GameView extends View {
        private Paint paint;

        public GameView(Context context) {
            super(context);
            paint = new Paint();
        }

        @Override
        protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
            super.onMeasure(widthMeasureSpec, heightMeasureSpec);
        }


        @Override
        protected void onDraw(Canvas canvas) {
            createAndShowGameView(canvas);

            try {
                Thread.sleep(50);
                if (!finished) {
                    checkIsDied();
                    checkIsWin();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            invalidate();
        }

        private void createAndShowGameView(Canvas canvas) {
            ClientView view = server.getClientView();
            updateMap(view.getGameView(), canvas);
        }

        private void updateMap(Icon[][] icons, Canvas canvas) {
            int numRows = icons.length;
            int numCols = icons[0].length;
            // north wall
            for (int c = 0; c < numCols + 2; c++) {
                canvas.drawBitmap(iconToImage(Icon.WALL), null, buildRectF(c, 0), paint);
            }
            for (int r = 0; r < numRows; r++) {
                // west wall
                canvas.drawBitmap(iconToImage(Icon.WALL), null, buildRectF(0, r + 1), paint);
                // maze contents
                for (int c = 0; c < numCols; c++) {
                    canvas.drawBitmap(iconToImage(icons[r][c]), null, buildRectF(c + 1, r + 1), paint);
                }
                // east wall
                canvas.drawBitmap(iconToImage(Icon.WALL), null, buildRectF(numCols + 1, r + 1), paint);
            }
            // south wall
            for (int c = 0; c < numCols + 2; c++) {
                canvas.drawBitmap(iconToImage(Icon.WALL), null, buildRectF(c, numRows + 1), paint);
            }
        }
    }

    public class MyGestureListener implements GestureDetector.OnGestureListener, GestureDetector.OnDoubleTapListener {

        @RequiresApi(api = Build.VERSION_CODES.KITKAT)
        @Override
        public void onLongPress(MotionEvent motionEvent) {
            showScore(server.checkScore());
        }

        @Override
        public boolean onFling(MotionEvent motionEvent, MotionEvent motionEvent1, float vx, float vy) {
            int minSpeed = 100;
            if (vx > minSpeed)
                server.moveHero(Direction.EAST);
            else if (vx < -minSpeed)
                server.moveHero(Direction.WEST);
            if (vy > minSpeed)
                server.moveHero(Direction.SOUTH);
            else if (vy < -minSpeed)
                server.moveHero(Direction.NORTH);
            return true;
        }

        @Override
        public boolean onDoubleTap(MotionEvent motionEvent) {
            server.pickTreasure();
            server.killMonster();
            return true;
        }

        @Override
        public boolean onSingleTapConfirmed(MotionEvent motionEvent) {
            return false;
        }

        @Override
        public boolean onDown(MotionEvent motionEvent) {
            return false;
        }

        @Override
        public void onShowPress(MotionEvent motionEvent) {

        }

        @Override
        public boolean onSingleTapUp(MotionEvent motionEvent) {
            return false;
        }

        @Override
        public boolean onScroll(MotionEvent motionEvent, MotionEvent motionEvent1, float v, float v1) {
            return false;
        }

        @Override
        public boolean onDoubleTapEvent(MotionEvent motionEvent) {
            return false;
        }
    }
}
